#!/bin/bash

PATH_TO_SCRIPT=`dirname $0`
function find_helper()
{
	IN_PATH=`which $1`
	REL_TO_PATH="$PATH_TO_SCRIPT/$2"
	if [ -z "$IN_PATH" ] && [ ! -z "$PATH_TO_SCRIPT" ] &&  [ -x "$PATH_TO_SCRIPT/$1" ]
	then
		echo "$PATH_TO_SCRIPT/$1"
	elif [ -z "$IN_PATH" ] && [ ! -z "$PATH_TO_SCRIPT" ] &&  [ -x "$REL_TO_PATH/$1" ]
	then
	    echo "$REL_TO_PATH/$1"
	else
		echo "$IN_PATH"
	fi
}

function die()
{
	echo "[EE] $*"
	exit 1
}

[ -z "$FTCAT" ] && FTCAT=`find_helper ftcat ../ft_tools`
[ -z "$FTCAT" ] && die "Can't find 'ftcat' utility."

[ -z "$SHOWSCHED" ] && SHOWSCHED=`find_helper showsched ../liblitmus`
[ -z "$SHOWSCHED" ] && die "Can't find 'showsched' utility."


if [ "$1" == "-s" ]
then
  AUTO=1
  shift
fi

PIDS=""

# signal that we're done gathering data and clean up
on_finish()
{
    echo "Ending Trace..."
    kill $PIDS
    wait $PIDS

    exit 0
}

# register shutdown signal handler
trap 'on_finish' SIGUSR1


CPU_FILES=`ls /dev/litmus/ft_cpu_trace* 2>/dev/null`
MSG_FILES=`ls /dev/litmus/ft_msg_trace* 2>/dev/null`

if [ -z "${CPU_FILES}${MSG_FILES}" ]
then
	echo "[EE] Could not find any trace files in /dev/litmus/."
	echo "     Is this a LITMUS^RT kernel?"
	echo "     If so, is CONFIG_SCHED_OVERHEAD_TRACE enabled?"
	die "No trace files found."
fi

NAME=$1
shift

[ -z "${NAME}" ] && die "No name specified. Run as 'ft-trace-overheads <NAME>'."


SCHED_EVENTS="SCHED2 SCHED CXS TICK RELEASE XCALL SCHED_TIMER QUANTUM_BOUNDARY"

CPU_EVENTS=
for x in $SCHED_EVENTS
do
	CPU_EVENTS="$CPU_EVENTS ${x}_END ${x}_START"
done
CPU_EVENTS="$CPU_EVENTS RELEASE_LATENCY TIMER_LATENCY"

IPI_EVENTS="SEND_RESCHED SEND_XCALL"
MSG_EVENTS=
for x in $IPI_EVENTS
do
	MSG_EVENTS="$MSG_EVENTS ${x}_END ${x}_START"
done

NAME=${NAME//[ \/]/-}

SCHEDULER=`$SHOWSCHED`
if (( $? != 0 ))
then
    SCHEDULER="UNKNOWN"
fi
SCHEDULER=${SCHEDULER//[ \/_]/-}

DIR=`mktemp -d` || die "mktemp failed"

COUNT=0
for dev in $CPU_FILES
do
	CPU=`basename ${dev} | sed 's/ft_cpu_trace//'`
	TRACE="overheads_host=`hostname`_scheduler=${SCHEDULER}_trace=${NAME}_cpu=${CPU}.bin"
	echo "[II] Recording $dev -> $TRACE"
	$FTCAT -p "$DIR/cpu$CPU.pid" $dev $CPU_EVENTS > $TRACE &
	PIDS="$PIDS $!"
	COUNT=$((COUNT + 1))
done

for dev in $MSG_FILES
do
	CPU=`basename ${dev} | sed 's/ft_msg_trace//'`
	TRACE="overheads_host=`hostname`_scheduler=${SCHEDULER}_trace=${NAME}_msg=${CPU}.bin"
	echo "[II] Recording $dev -> $TRACE"
	$FTCAT -p "$DIR/msg$CPU.pid" $dev $MSG_EVENTS > $TRACE &
	PIDS="$PIDS $!"
	COUNT=$((COUNT + 1))
done

READY=`ls $DIR/*.pid 2>/dev/null | wc -l`
while [[ $READY != $COUNT ]]
do
    sleep 0.5
    READY=`ls $DIR/*.pid 2>/dev/null | wc -l`
done

rm $DIR/*.pid
rmdir $DIR


if [[ $AUTO != 1 ]]
then
    echo "Press Enter to end tracing..."
    read
    on_finish
else
    # wait for SIGUSR1 to terminate
    echo "Waiting for SIGUSR1 to end tracing..."
    wait $PIDS
fi
